﻿//由W意波(LuoJun)编写，除了对左右值引用类型的const、volite、pointer判定外，其它判定结果跟标准库一致
#ifndef LK_TYPE_
#define LK_TYPE_
#include <vector>
namespace LK
{
	//声明PFunObjs
	namespace Functional { struct PFunObjs; }
	//记录类型通用函数数据
	struct CommonTypeFunctionInfoStruct
	{
		//类型大小
		index_t size;
		//构造方法
		void(*DefaultConstructMethod)(void*);
		//析构方法
		void(*DeconstructMethod)(void*);
		//复制构造方法
		void(*CopyConstructMethod)(void*, const void*);
		//默认方法
		template<class T>static void DefDefaultConstructMethod(void* p) { placementnew((T*)p); }
		template<class T>static void DefCopyConstructMethod(void* pd, void const*ps) { placementnew((T*)pd, *(const T*)ps); }
		template<class T>static void DefDeconstructMethod(void* p) { ((T*)p)->T::~T(); }
		CommonTypeFunctionInfoStruct()//默认构造
		{
			CopyConstructMethod = NULL;
			DeconstructMethod = NULL;
			DefaultConstructMethod = NULL;
			size = 0;
		}
		PString& GetNameRef();
	private:
		PObject Name;
	};

	/**
	@brief 比较是否相等
	@note 不会抛出异常*/
	bool operator==(PType const&t1, PType const &t2);
	bool operator!=(PType const&t1, PType const &t2);
	/**
	@brief 比较大小关系，如果一方为NULL将抛出空指针异常*/
	bool operator>=(PType const&t1, PType const &t2);
	bool operator<=(PType const&t1, PType const &t2);
	bool operator>(PType const&t1, PType const &t2);
	bool operator<(PType const&t1, PType const &t2);

	typedef ptr<Type> type;
	PTRPREDEFINE(,Type)

	template<class T, bool isfun = ::LK::IsFunction<T>::V>struct _TypeMaker { static inline PType Make(); };
	template<class T>struct _TypeMaker<T,true>{static inline PType Make();};
	template<class T>struct _TypeMaker<T*,false>{static inline PType Make();};
	template<class T,index_t C>struct _TypeMaker<T[C], false>{static inline PType Make();};
#ifdef _CLR
	template<class T>struct _TypeMaker<T^,false>{static inline PType Make();};
	template<class T>struct _TypeMaker<gcroot<T^>,false>{static inline PType Make();};
#endif
	struct Type : ICloneables
	{
	private:
		static Mutex& GetMutexRef() { static Mutex mto; return mto; }
		template <class T>static inline PType MakeArray();
		template <class T>static inline PType MakeFunction();
		template <class T>static inline PType MakePointer();
		template <class T>static inline PType MakeNormal();
		template <class T>static inline PType MakeType(size_t extents);
		friend struct ptr<Type>;
		template<class T, bool v>friend struct _TypeMaker;
		//调用初始化函数（防止重复调用）
		static void CallAddTypeInfoFunction(void(*)());
		//判断两个type是否是指针而且可转换
		static bool IsPointerConvertible(Type const& from, Type const&to);
		template<class T>static long GetId1();
		/**
		@brief 获取本地唯一类型Id，每获取一次就+1，结果永远大于0*/
		static index_t GetLocalTypeId(){
			//前17个基本数据类型void,bool,s8,s16,i32,s32,s64,u8,u16,ui32,u32,u64,float,double,long double,char,wchar_t
			//18是gcroot模板，19是托管类型
			static index_t index = 19;
			return ++index;
		}
		/**
		@brief 获取动态唯一类型Id，每获取一次就-1，结果永远小于0*/
		static index_t GetDynamicTypeId(){
			static index_t index = 0;
			return --index;
		}
		/**
		@brief 如果跟函数类型有关系，则表示函数的返回值类型和参数类型（可变参最后一个参数为空引用，而且可变参算一个参数）*/
		std::vector<PType >funArgs;
		/**
		@brief 数组和指针信息
		[x]表示指针层级时<0，且[x+n]用以记录const和volatile限定，[x+n+1]跟[x]相等；
		[x]表示数组时大于0，且[x+k]记录const和volatile限定(如果x+k在最末尾，则交给attr来记录)*/
		std::vector<index_t>props;
		/**
		@brief 记录最外层类型特性，包括引用、volatile、const等*/
		size_t attr;
		/**
		@brief 原始类型id*/
		index_t ID;
#ifdef _CLR
		/**
		@brief 关联的托管类型信息*/
		gcroot<System::Type^> gctype;
#endif
	public:
		/**
		@brief 获取参数包内的所有参数，并打包为一个vector*/
		template <class T>static std::vector<PType > GetTypesFromArgs();
		template <class T>static PString GetStringFromArgs();
		/**
		@brief 获取Type类的类型信息*/
		virtual PType GetType()const;
		/**
		@brief 获取新的对象*/
		virtual Type* Clone()const;
		/**
		@brief 获取记录全局对象通用信息的vector引用*/
		static std::vector<CommonTypeFunctionInfoStruct>& GetTypeCommonInfoRef();
		/**
		@brif 添加类型信息*/
		static void AddTypeInfo();
		/**
		@brief 获取特性描述字*/
		size_t GetAttribute()const { return attr; }
		/**
		@brief 根据模板参数T生成类型信息*/
		template <class T>static inline PType Make();
		/**
		@brief 获取类型T的ID，该方法线程安全
		@note 类型T必须是最原生类型，否则将无法编译通过*/
		template<class T>static inline typename UseIf<!::LK::IsFunction<T>::V&&!::LK::IsArray<T>::V&&
			!::LK::IsPointer<T>::V&&::LK::IsSame<typename ::LK::RemoveAllExtents<T>::T, T>::V,
			long>::T
			GetId() { return GetId1<T>(); }
		/**
		@brief 默认构造函数，构造空类型*/
		Type() :funArgs(), props(), attr(0), ID(0) {}
		/**
		@brief 使用一个类型Id和最外层限定特性来构造*/
		Type(index_t id, size_t at = 0) :funArgs(), props(), attr(at), ID(id) {}
		/**
		@brief 析构函数*/
		~Type() {}
		/**
		@brief 转变为指向该类型的指针类型，cnt表示添加的指针层级，默认为1;ar为外层限定特性，默认为0*/
		Type& SelfToPointer(index_t cnt = 1, size_t at = 0);
		/**
		@brief 转变为指向该类型的数组类型，cnt表示该维元素数*/
		Type& SelfToArray(index_t cnt);
		/**
		@brief 转变为该类型解引用的类型，cnt表示解引用次数，默认为1
		@note 该方法可以用于减小数组维数*/
		Type& SelfToPointed(index_t cnt = 1);
		/**
		@brief 设置函数类型
		@note types[0]表示返回值类型，types[1]开始表示参数类型。如果是可变参函数，最后一个元素请置空*/
		void SetFunctionArgs(std::vector<PType>types);
		/**
		@brief 是否函数*/
		bool IsFunction()const { return funArgs.size() != 0 && props.size() == 0; }
		/**
		@brief 是否是纯类型(指针、数组、函数、带限定者都不算纯类型)*/
		bool IsPureType()const { return funArgs.size() == 0 && props.size() == 0 && attr == 0; }
		/**
		@brief 是否是纯类型，忽略扩展*/
		bool IsPureTypeIgnoreExtents()const { return funArgs.size() == 0 && props.size() == 0; }
		/**
		@brief 是否是数组类型（忽略最外层引用、const、volatile特性）*/
		bool IsArray()const { return props.size() > 0 && props.back() > 0; }
		/**
		@brief 是否是指针类型（忽略最外层引用、const、volatile特性）*/
		bool IsPointer()const { return props.size() != 0 && props.back() < 0; }
		/**
		@brief 是否是const*/
		bool IsConst()const { return attr&TypeExtents::Const; }
		/**
		@brief 是否是volatile*/
		bool IsVolatile()const { return (attr&TypeExtents::Volatile) != 0; }
		/**
		@brief 是否是托管类型*/
		bool IsGCType()const {return ID==19;}
		/**
		@brief 是否是托管句柄*/
		bool IsGCHandle()const {return IsGCType()&&props.size()==0&&funArgs.size()==0;}
		/**
		@brief 是否是左值引用*/
		bool IsLValueReference()const { return (attr&TypeExtents::LValueReference) != 0; }
		/**
		@brief 是否是右值引用*/
		bool IsRValueReference()const { return (attr&TypeExtents::RValueReference) != 0; }
		/**
		@brief 是否是引用*/
		bool IsReference()const { return IsLValueReference() || IsRValueReference(); }
		/**
		@brief 是否可变参函数*/
		bool IsVaridicFunction()const { return funArgs.size() != 0 && funArgs.back()==null; }
		/**
		@brief 判断该类型的原始类型是否从另一类型派生，或者两种类型相同*/
		bool IsDerivedFrom(PType const& t)const;
		//动态类型转换（lv为0时进行基础转换，1进行精确转换，2进行模糊转换）
		PObject DynamicConvertFrom(PObject const& obj, index_t lv = 2)const;
		//判断是否可从from类型转换到该类型
		bool CanDynamicConvertFrom(PType const&, index_t lv = 2)const;
		/**
		@brief 获取数组维数*/
		index_t GetArrayLevel()const;
		/**
		@brief 获取数组指定维上的元素数，比如对于数组类型int[5][4]，传入参数为0时返回5，传入2时返回0*/
		index_t GetElementCount(index_t d)const;
		/**
		@brief 获取全称*/
		PString GetFullName(PString instr)const;
		/**
		@brief 获取名称*/
		PString GetName(PString instr)const;
		/**
		@brief 获取全称*/
		PString GetFullName()const;
		/**
		@brief 获取名称*/
		PString GetName()const;
		/**
		@brief 获取类型ID*/
		index_t GetID()const { return ID; }
		/**
		@brief 获取大小（如果为左值引用，则为指针大小）*/
		index_t GetSize()const { if (IsLValueReference() || funArgs.size() != 0 || props.size() != 0)return sizeof(void*); return GetTypeCommonInfoRef()[ID].size; }
		/**
		@brief 获取大小(忽略引用)*/
		index_t GetSizeIgnoreReference()const { if (funArgs.size() != 0 || props.size() != 0)return sizeof(void*); return GetTypeCommonInfoRef()[ID].size; }
		/**
		@brief 比较*/
		friend bool operator==(Type const&t1, Type const&t2) { return t1.ID == t2.ID&&t1.attr == t2.attr&&t1.props == t2.props&&t1.funArgs == t2.funArgs; }
		friend bool operator!=(Type const&t1, Type const&t2) { return !(t1 == t2); }
		/**
		@brief 比较两个类型信息的大小*/
		index_t CompareWith(PType const&)const;
		/**
		@brief 忽略attr限定进行比较*/
		index_t CompareWithoutExtents(PType const&t)const;
		/**
		@breif 对数据地址p使用该类型的默认构造函数构造*/
		void DefaultConstruct(void* p)const;
		/**
		@breif 对数据地址p使用该类型的析构函数析构*/
		void Deconstruct(void* p)const;
		/**
		@breif 使用数据地址ps的内容使用该类型的复制构造方法写到数据地址pd中*/
		void CopyConstruct(void* pd, void const*ps)const;
		/**
		@breif 对数据地址p使用该类型的默认构造函数构造（忽略引用特性）*/
		void DefaultConstructIgnoreReference(void* p)const;
		/**
		@breif 对数据地址p使用该类型的析构函数析构（忽略引用特性）*/
		void DeconstructIgnoreReference(void* p)const;
		/**
		@breif 使用数据地址ps的内容使用该类型的复制构造方法写到数据地址pd中（忽略引用特性）*/
		void CopyConstructIgnoreReference(void* po, void const*ps)const;
		/**
		@brief 同类型数据引用转换*/
		static PMObjects SameTypeReferenceConvert(PType const& to, PMObjects const& src);
		/**
		@brief 同类型数据引用转换*/
		static PMObjects SameTypeReferenceConvert(PType const& to, PObject const& src);
	};
	template <class T>std::vector<PType > Type::GetTypesFromArgs()
	{
		if (IsSame<::LK::VarArgsPack<>, T>::V)
			return std::vector<PType>();
		typedef typename ::LK::UseT<::LK::IsSame<::LK::VarArgsPack<>, T>::V, T, ::LK::VarArgsPack<void> >::T TT;
		std::vector<PType>tmp = Type::GetTypesFromArgs<typename ::LK::ArgRemoveAt<0, TT >::T >();
		tmp.insert(tmp.begin(), Type::Make<typename ArgT<0, TT>::T >());
		return tmp;
	}
	template <class T>inline PType Type::MakeType(size_t extents){
		static PType*p;
		if (!p) {
			GetMutexRef().Lock();
			if (!p){
				static PType t = _TypeMaker<T>::Make();
				p = &t;
				if (IsBaseOf<PObject, T>::V)//调用AddTypeInfo函数
				{
					typedef typename TypeOfReference<typename UseT<IsBaseOf<PObject, T>::V, PObject, T>::T>::T TClass;
					Type::CallAddTypeInfoFunction(&TClass::AddTypeInfo);
				}
			}
			GetMutexRef().UnLock();
		}
		if(extents==0&&!::LK::IsFunction<T>::V)return *p;
		PObject tmp = ((*p)->Clone());
		PType t = (PType&)tmp;
		t.Check()->attr = extents;
		return t;
	}
	template <class T>inline PType Type::Make(){
		return MakeType<typename RemoveAllExtents<T>::T>(ExtentsOf<T>::V);
	}
	template <class T,index_t C>inline PType _TypeMaker<T[C], false>::Make()
	{
		PType t = Type::Make<T>();
		Convert<PType,PObject>::RefFrom(ICloneables::OnePtr(t))->SelfToArray(C);
		return t;
	}
	template <class T>inline PType _TypeMaker<T, true>::Make()
	{
		PType t = new Type();
		t.GetPtr()->SetFunctionArgs(Type::GetTypesFromArgs<typename ::LK::IsFunction<T>::T>());
		t.GetPtr()->ID = Type::GetId<typename ::LK::ArgT<1, typename ::LK::IsFunction<T>::T>::T>();
		if ((::LK::IsFunction<T>::type &::LK::TypeExtents::Variable) != 0)//可变参添加一个空参数
			t.GetPtr()->funArgs.push_back(PType());
		return t;
	}
	template <class T>inline PType _TypeMaker<T*, false>::Make()
	{
		PType t = Type::Make<T>();
		Convert<PType,PObject>::RefFrom(ICloneables::OnePtr(t))->SelfToPointer();
		return t;
	}
	template <class T,bool isf>inline PType _TypeMaker<T,isf>::Make()
	{
		PType t = new Type(Type::GetId<T>());
		return t;
	}
#ifdef _CLR
	template<class T>inline PType _TypeMaker<T^, false>::Make(){
		PType t = new Type(19);
		t->gctype = T::typeid;
		return t;
	}
	template<class T>inline PType _TypeMaker<gcroot<T^>, false>::Make(){
		PType t = new Type(18);
		t->gctype = T::typeid;
		return t;
	}
#endif

}
#endif
